package cn.kai.util;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.extra.cglib.CglibUtil;
import cn.kai.base.BaseQueryDto;
import cn.kai.vo.PageVO;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 转换相关工具类
 * Author: cKnight
 * Date: 2024/6/11
 */
@Slf4j
public class ConvertUtils {


    /**
     * pageMap转化 需要DO 转 VO
     *
     * @param page
     * @param toClass
     * @return
     */
    public static <I, O> PageVO<O> toPageResult(Page<I> page, Class<O> toClass) {
        PageVO<O> result = new PageVO<>();
        result.setTotalPage(page.getPages());
        result.setTotalRecord(page.getTotal());
        result.setRows(listFromTo(page.getRecords(), toClass));
        return result;
    }

    public static <I> PageVO<I> toPageResult(Page<I> page) {
        PageVO<I> result = new PageVO<>();
        result.setTotalPage(page.getPages());
        result.setTotalRecord(page.getTotal());
        result.setRows(page.getRecords());
        return result;
    }


    public static <I, O> PageVO<O> toPageResult(Page<I> page, List<O> list) {
        PageVO<O> result = new PageVO<>();
        result.setTotalPage(page.getPages());
        result.setTotalRecord(page.getTotal());
        result.setRows(list);
        return result;
    }

    public static <I, O> PageVO<O> toPageResult(PageVO<I> page, List<O> list) {
        PageVO<O> result = new PageVO<>();
        result.setTotalPage(page.getTotalPage());
        result.setTotalRecord(page.getTotalRecord());
        result.setRows(list);
        return result;
    }

    public static <I, O> PageVO<O> toPageResult(PageVO<I> page, Class<O> clazz) {
        PageVO<O> result = new PageVO<>();
        result.setTotalPage(page.getTotalPage());
        result.setTotalRecord(page.getTotalRecord());
        result.setRows(listFromTo(page.getRows(),clazz));
        return result;
    }

    public static <I, O> PageVO<O> toPageResult(int pageNum, int pageSize, List<O> list) {
        PageVO<O> result = new PageVO<>();
        result.setTotalPage((long)PageUtil.totalPage(list.size(), pageSize));
        result.setTotalRecord((long)list.size());
        result.setRows(ListUtil.page(pageNum-1, pageSize, list));
        return result;
    }

    public static <O> PageVO<O> toPageResult(List<O> list, BaseQueryDto queryDto) {
        return toPageResult(queryDto.getPageNum(),queryDto.getPageSize(),list);
    }

    /**
     * 单个对象转换
     *
     * @param from
     * @param clazz
     * @param <I>
     * @param <O>
     * @return
     */
    public static <I, O> O beanProcess(I from, Class<O> clazz) {
        if (Objects.isNull(from)){
            return null;
        }
        return CglibUtil.copy(from,clazz);
    }


    /**
     * list DO 转 VO
     *
     * @param list
     * @param clazz
     * @return
     */
    public static <I, O> List<O> listFromTo(List<I> list, Class<O> clazz) {
        if (CollectionUtils.isEmpty(list)){
            return Collections.emptyList();
        }
        return list.stream().map(obj -> beanProcess(obj, clazz)).collect(Collectors.toList());
    }


    /**
     * list转字段list
     * @param list
     * @param function
     * @return
     * @param <I>
     * @param <O>
     */
    public static <I,O> List<O> toFieldList(List<I> list, Function<I,O> function){
        if (CollectionUtils.isEmpty(list)){
            return Collections.emptyList();
        }
        return list.stream().map(function).collect(Collectors.toList());
    }

    /**
     * list转字段Set
     *
     * @param list     源list
     * @param function 字段
     * @param <I>      源对象类型
     * @param <O>      转换对象类型
     * @return Set集合
     */
    public static <I, O> Set<O> toFieldSet(List<I> list, Function<I, O> function) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptySet();
        }
        return list.stream().map(function).collect(Collectors.toSet());
    }

    /**
     * 去重
     */
    public static <I,O> List<O> toFieldDistinctList(List<I> list, Function<I,O> function){
        return toFieldList(list,function).stream().distinct().collect(Collectors.toList());
    }

    /**
     * 过滤 获取任意一个
     * @param list
     * @param predicate
     * @return
     * @param <T>
     */
    public static <T> T toFilterOne(List<T> list, Predicate<T> predicate){
        if (list.stream().anyMatch(predicate)){
            return list.stream().filter(predicate).findAny().get();
        }
        return null;
    }

    /**
     * 筛选集合后获取指定属性
     * @param list
     * @param predicate
     * @param function
     * @param <I>
     * @param <O>
     * @return
     */
    public static <I,O> O processList(List<I> list,Predicate<I> predicate,Function<I,O> function) {
        I filterOne = ConvertUtils.toFilterOne(list, predicate);
        if (Objects.nonNull(filterOne)){
            return function.apply(filterOne);
        }else {
            return null;
        }
    }

    public static <T> List<T> toList(List<Object> list,Class<T> clazz){
        return list.stream().filter(Objects::nonNull)
                .map(obj-> JSONObject.parseObject(JSONObject.toJSONString(obj))
                        .toJavaObject(clazz))
                .collect(Collectors.toList());
    }

    public static <K,V> List<V> map2List(Map<K,V> map){
        return map.entrySet().stream().map(Map.Entry::getValue).collect(Collectors.toList());
    }
    /**
     * 安全地将Object转换为指定类型的List
     *
     * @param obj 需要转换的对象
     * @param clazz 目标类型
     * @return 转换后的List
     */
    public static <T> List<T> convertToList(Object obj, Class<T> clazz) {
        if (obj == null) {
            return Collections.emptyList();
        }
        return JSON.parseArray(JSON.toJSONString(obj), clazz);
    }
}
